﻿using System.IO;
using System.Linq;
using System;
using ClassMetadataBrowser.Domain;

namespace ClassMetadataBrowser
{
	internal class MetadataFilesWatcher : IDisposable
	{
		private const string CodeFilesExtensions = ".cs,.vb";
		private readonly string _solutionPath;
		private readonly IMetadataProvider _provider;
		private readonly FileSystemWatcher _watcher;
		private string _filePath;

		public MetadataFilesWatcher(string solutionPath, IMetadataProvider provider)
		{
			_solutionPath = solutionPath;
			_provider = provider;

			// initializing filewatcher
			_watcher = new FileSystemWatcher();
			_watcher.Path = _solutionPath;
			_watcher.IncludeSubdirectories = true;
		}

		public MetadataFilesWatcher(IMetadataProvider provider)
		{
			_provider = provider;

			// initializing filewatcher
			_watcher = new FileSystemWatcher();
			_watcher.IncludeSubdirectories = true;
		}

		public void Start(string filePath)
		{
			_filePath = filePath;
			_watcher.Path = Path.GetDirectoryName(filePath);
			_watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
				| NotifyFilters.FileName | NotifyFilters.DirectoryName;
			_watcher.Changed += new FileSystemEventHandler(FileChanged);
			_watcher.Created += new FileSystemEventHandler(FileCreated);
			_watcher.Deleted += new FileSystemEventHandler(FileDeleted);
			_watcher.Renamed += new RenamedEventHandler(FileRenamed);
			_watcher.EnableRaisingEvents = true;
		}

		private void FileRenamed(object sender, RenamedEventArgs e)
		{
			if (!IsFileValid(e.FullPath))
				return;

			_provider.ReInitializeMetadata(e.OldFullPath, e.FullPath);
		}

		private void FileDeleted(object sender, FileSystemEventArgs e)
		{
			if (!IsFileValid(e.FullPath))
				return;

			_provider.ReInitializeMetadata(e.FullPath, e.FullPath);
		}

		private void FileCreated(object sender, FileSystemEventArgs e)
		{
			if (!IsFileValid(e.FullPath))
				return;

			_provider.ReInitializeMetadata(e.FullPath, e.FullPath);
		}

		private void FileChanged(object sender, FileSystemEventArgs e)
		{
			if (!IsFileValid(e.FullPath))
				return;

			_provider.ReInitializeMetadata(e.FullPath, e.FullPath);
		}

		private bool IsFileValid(string fileFullPath)
		{
			if (!string.IsNullOrEmpty(_filePath) &&
				fileFullPath == _filePath)
				return true;

			string[] extensions = CodeFilesExtensions.Split(',');
			return extensions.Contains(Path.GetExtension(fileFullPath));
		}

		#region IDisposable Members

		public void Dispose()
		{
			_watcher.Dispose();
		}

		#endregion
	}
}
